<?php

namespace app\service;

use app\tool\SingletonTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class RoleService
{
    use SingletonTrait;

    protected $roleData = [];
    protected array $byId = [];
    protected array $byCode = [];

    /**
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function __construct()
    {
        $this->roleData = (new \app\model\RoleModel())->cache()->select();
        $this->byId = $this->roleData->column(null, 'id');
        $byCodeList = $this->roleData->column(null, 'code');
        $this->byCode = array_map(function ($tmp) {
            $tmp['id'] = intval($tmp['id']);
            return $tmp;
        }, $byCodeList);
    }

    /**
     * @param $roleCode
     * @return mixed|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function find($roleCode)
    {
        $roleData = (new \app\model\RoleModel)->field('id')->where('code', $roleCode)->find();
        if (empty($roleData['id'])) {
            return null;
        }
        return $roleData['id'];
    }

    public function byId(int $roleId, string $column = null)
    {
        if (!empty($column)) {
            return $this->byId[$roleId][$column] ?? null;
        }
        return $this->byId[$roleId] ?? null;
    }

    public function byCode(string $roleCode, string $column = null)
    {
        if (!empty($column)) {
            return $this->byCode[$roleCode][$column] ?? null;
        }
        return $this->byCode[$roleCode] ?? null;
    }

    /**
     * @param array $roleCodeList
     * @param bool $exclude
     * @param string|null $implodeKey
     * @return array|string
     */
    public function byCodeMap(array $roleCodeList, bool $exclude = false, string $implodeKey = null)
    {
        $res = [];
        if (!$exclude) {
            foreach ($roleCodeList as $code) {
                if (isset($this->byCode[$code])) {
                    $res[$code] = $this->byCode[$code];
                }
            }
        } else {
            foreach ($this->byCode as $code => $item) {
                if (!in_array($code, $roleCodeList)) {
                    $res[$code] = $item;
                }
            }
        }
        if (!empty($implodeKey)) {
            return implode(',', array_column($res, $implodeKey));
        }
        return $res;
    }
}
